import {computed, onUnmounted, reactive, ref, watch,} from 'vue'
import {IClientPublishOptions, IPublishPacket,} from '/@/mqtt'
import {useMyStore} from '/@/store'
import {DRC_METHOD,} from '/@/types/drc'
import EventBus from '/@/event-bus'

export interface DeviceTopicInfo {
    sn: string
    pubTopic: string
    subTopic: string
}

type MessageMqtt = (topic: string, payload: Buffer, packet: IPublishPacket) => void | Promise<void>

export function useMqtt(deviceTopicInfo: DeviceTopicInfo) {
    let cacheSubscribeArr: {
        topic: string;
        callback?: MessageMqtt;
    }[] = []

    const store = useMyStore()

    const mqttState = computed(() => {
        return store.state.mqttState
    })

    function publishMqtt(topic: string, body: object, ots?: IClientPublishOptions) {
        // const buffer = Buffer.from(JSON.stringify(body))
        mqttState.value?.publishMqtt(topic, JSON.stringify(body), ots)
    }

    function subscribeMqtt(topic: string, handleMessageMqtt?: MessageMqtt) {
        mqttState.value?.subscribeMqtt(topic)
        const handler = handleMessageMqtt || onMessageMqtt
        mqttState.value?.on('onMessageMqtt', handler)
        cacheSubscribeArr.push({
            topic,
            callback: handler,
        })
    }

    function onMessageMqtt(message: any) {
        if (cacheSubscribeArr.findIndex(item => item.topic === message?.topic) !== -1) {
            const payloadStr = new TextDecoder('utf-8').decode(message?.payload)
            const payloadObj = JSON.parse(payloadStr)
            switch (payloadObj?.method) {
                case DRC_METHOD.HEART_BEAT:
                    break
                case DRC_METHOD.DELAY_TIME_INFO_PUSH:
                case DRC_METHOD.HSI_INFO_PUSH:
                case DRC_METHOD.OSD_INFO_PUSH:
                case DRC_METHOD.DRONE_CONTROL:
                case DRC_METHOD.DRONE_EMERGENCY_STOP:
                    EventBus.emit('droneControlMqttInfo', payloadObj)
                    break
                default:
                    break
            }
        }
    }

    function unsubscribeDrc() {
        // 销毁已订阅事件
        cacheSubscribeArr.forEach(item => {
            mqttState.value?.off('onMessageMqtt', item.callback)
            mqttState.value?.unsubscribeMqtt(item.topic)
        })
        cacheSubscribeArr = []
    }

    // 心跳
    const heartBeatSeq = ref(0)
    const state = reactive({
        heartState: new Map<string, {
            pingInterval: any;
        }>(),
    })

    // 监听云控控制权
    watch(() => deviceTopicInfo, (val, oldVal) => {
        if (val.subTopic !== '') {
            // 1.订阅topic
            subscribeMqtt(deviceTopicInfo.subTopic)
            // 2.发心跳
            publishDrcPing(deviceTopicInfo.sn)
        } else {
            clearInterval(state.heartState.get(deviceTopicInfo.sn)?.pingInterval)
            state.heartState.delete(deviceTopicInfo.sn)
            heartBeatSeq.value = 0
        }
    }, {immediate: true, deep: true})

    function publishDrcPing(sn: string) {
        const body = {
            method: DRC_METHOD.HEART_BEAT,
            data: {
                ts: new Date().getTime(),
                seq: heartBeatSeq.value,
            },
        }
        const pingInterval = setInterval(() => {
            if (!mqttState.value) return
            heartBeatSeq.value += 1
            body.data.ts = new Date().getTime()
            body.data.seq = heartBeatSeq.value
            publishMqtt(deviceTopicInfo.pubTopic, body, {qos: 0})
        }, 1000)
        state.heartState.set(sn, {
            pingInterval,
        })
    }

    onUnmounted(() => {
        unsubscribeDrc()
        heartBeatSeq.value = 0
    })

    return {
        mqttState,
        publishMqtt,
        subscribeMqtt,
    }
}
